#-*-coding:utf-8-*-
import shapefile as shp
import csv
import codecs
import os,sys,time
import chardet

# 获取当前时间
def currentTime():
    return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))

# 计算时间差
def timeDalta(startTime, endTime):
    from datetime import datetime 
    format = '%Y-%m-%d %H:%M:%S'
    a = datetime.strptime(startTime, format)
    b = datetime.strptime(endTime, format)
    t1 = time.mktime(a.timetuple()) * 1000 + a.microsecond / 1000
    t2 = time.mktime(b.timetuple()) * 1000 + b.microsecond / 1000
    seconds = int((t2 - t1) / 1000)
    _seconds = str(seconds) + '秒' if seconds>0 else ''
    minites = int(seconds / 60)
    _minites = str(minites) + '分' if minites>0 else ''
    hours = int(minites / 60)
    _hours = str(hours) + '时' if hours>0 else ''
    days = int(hours / 24)
    _days = str(days) + '天' if days>0 else '' 
    times = "总耗时：" + _days + _hours + _minites + _seconds
    return times

def detectCode(path):
    with open(path, 'rb') as file:
        data = file.read(20000)
        dicts = chardet.detect(data)
    return dicts["encoding"]


shpType = {
    'NULL':0,
    'POINT':1,
    'POLYLINE':3,
    'POLYGON':5,
    'MULTIPOINT':8,
    'POINTZ':11,
    'POLYLINEZ':13,
    'POLYGONZ':15,
    'MULTIPOINTZ':18,
    'POINTM':21,
    'POLYLINEM':23,
    'POLYGONM':25,
    'MULTIPOINTM':28,
    'MULTIPATCH':31
    }

fileType = {
    'string':'C', # 字符，文字。
    'int':'N', # 数字，带或不带小数。
    'float':'F', # 浮动（与“N”相同）。
    'logic': 'L', # 逻辑，表示布尔值True / False值。
    'date':'D', # 日期。
    'note':'M'# 备忘录，在GIS中没有意义，而是xbase规范的一部分
}

# 从网络获取投影信息
def getWKT_PRJ (epsg_code):
    import urllib.request as urllib
    print('正在请求投影文件')
    wkt = urllib.urlopen("http://spatialreference.org/ref/epsg/{0}/prettywkt/".format(epsg_code))
    remove_spaces = wkt.read()#.replace(" ","") 
    output = remove_spaces.replace("\n", "")
    return output

# 默认生成 WGS_1984 投影文件
def initWGS1984 ():
    wkt = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]'
    return wkt

# 生成 shp 文件
def createShapfile(csvItem, shpPath, delimiter=','):
    # 创建 shp 文件
    output_shp = shp.Writer(shpPath)
    # 记录数据与几何数据对齐
    output_shp.autoBalance = 1
    # 设置 shp 属性表
    filedList = []
    with codecs.open(csvItem, 'rb', 'utf-8-sig') as csvfile:
        table = csv.reader(csvfile, delimiter=',')
        cursor = {
            'x': 0,
            'y': 0,
            'paths': 0,
            'rings': 0
        }
        for j in table:
            n = 0
            for k in j:
                filedList.append(k)
                if "x" in k:
                    output_shp.field('longitude', fileType["float"], 10, 8)
                    cursor["x"] = n
                elif "y" in k:
                    output_shp.field('latitude', fileType["float"], 10, 8)
                    cursor["y"] = n
                elif "paths" in k:
                    cursor["paths"] = n
                elif "rings" in k:
                    cursor["rings"] = n
                else:
                        output_shp.field(k,'C',255)
                n = n+1
            break
    # 设置 shp 要素类型
    if "paths" in ",".join(filedList):
        output_shp.shapeType = shpType['POLYLINE']
        print('%s | 图层类型为：%s '%(currentTime(), "线"))
    if "x" in ",".join(filedList):
        output_shp.shapeType = shpType['POINT']
        print('%s | 图层类型为：%s '%(currentTime(), "点"))
    if "rings" in ",".join(filedList):
        output_shp.shapeType = shpType['POLYGON']
        print('%s | 图层类型为：%s '%(currentTime(), "面"))
    # 遍历列表写入要素
    with codecs.open(csvItem, 'rb', detectCode(csvItem)) as csvfile:
        reader = csv.reader(csvfile, delimiter=delimiter)
        # 跳过表头
        next(reader, None)
        box = []
        index = 1
        # 遍历每条记录写入要素属性表
        for row in reader:
            list = []
            # 遍历字段列表并暂存
            for i in range(0,len(filedList)):
                if row[i] != "":
                    list.append(row[i])
            # 创建点要素
            if cursor["x"] > 10:
                x = float(row[cursor["x"]])
                y = float(row[cursor["y"]])
                output_shp.point(x, y)
                print("%s | 当前进度：%s 点要素层文件，总体进度 [%d / %d]"%(currentTime(), csvName, index, reader.line_num-1),end='\r')
            # 创建线要素
            if cursor["paths"] > 0:
                paths = row[cursor["paths"]].split(',')
                _paths = []
                for i in range(0, len(paths)):
                    if (i+1)%2 == 1:
                        _paths.append([float(paths[i]), float(paths[i+1])])
                output_shp.line([_paths])
                print("%s | 当前进度：%s 线要素层文件，总体进度 [%d / %d]"%(currentTime(),csvName, index, reader.line_num-1),end='\r')
            # 创建面要素
            if cursor["rings"] > 0:
                rings = row[cursor["rings"]].split(',')
                print(reader.line_num-1)
                _rings = []
                for i in range(0, len(rings)):
                    if (i+1)%2 == 1:
                        _rings.append([float(rings[i]), float(rings[i+1])])
                output_shp.poly([_rings])
                print("%s | 当前进度：%s 面要素层文件，总体进度 [%d / %d]"%(currentTime(),csvName, index, reader.line_num-1),end='\r')
            # 存入属性表
            output_shp.record(*list)
            index = index + 1
        print('')

if __name__ == '__main__':
    # 当前路径
    currentPath = os.getcwd()
    # 开始时间
    startTime = currentTime()
    # shp 输出路径
    outPutPath = os.getcwd() + '\\shp'
    # csv 读取路径
    csvPath = currentPath + '\\csv'
    print("%s | 读取列表..."%(currentTime()),file=sys.stdout)
    # csv 列表
    csvList =  os.listdir(csvPath)
    # 遍历 csv 路径下所有的文件
    for i in csvList:
        # 游标到每项 csv
        csvItem = csvPath + '\\' + i
        # 获取文件名
        csvName = i.split('.')[0]
        # 设置 shp 导出路径
        shpPath = outPutPath + '\\' + csvName
        print('%s | 开始生成 %s.shp '%(currentTime(), csvName))
        # 执行生成程序
        createShapfile(csvItem, shpPath)
        # 生成投影文件
        prj = open(shpPath + ".prj", "w")
        epsg = initWGS1984()
        prj.write(epsg)
        prj.close()
        print('%s | %s.shp 已生成结束'%(currentTime(), csvName))
    endTime = currentTime()
    print(timeDalta(startTime, endTime))
    
